package com.pagepub.core.tag.validate;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.Form;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorResources;
import org.apache.commons.validator.Var;

import com.pagepub.core.exception.ExceptionMessageParam;
import com.pagepub.core.exception.SysException;
import com.pagepub.core.utils.StringUtil;
import com.pagepub.core.utils.SystemCfgHelper;
import com.pagepub.core.utils.SystemUtil;


/**
 * 创建客户端脚本验证类
 * @author ggd
 *
 */
public class CreateJavascriptUtil
{
	private static Log log = LogFactory.getLog(CreateJavascriptUtil.class);

	private static ValidatorResources resources = null;

	/**
	 * 取得配置表单中有配置的field,并取他对应的javascript代码出来
	 */

	static
	{
		initVR();// 初始化ValidatorResources
	}

	/**
	 * 初始化ValidatorResources validator-rules.xml和validation.xml配置文件放在class根目录下面

	 * 
	 * @param vr
	 */
	private static void initVR()
	{
		try
		{
			if (resources == null)
			{
				String[] cfgFileNames = SystemCfgHelper.getValitorCfgFileName().split(",");
				String[] uris = new String[cfgFileNames.length];
				for (int i = 0; i < uris.length; i++)
				{
					// 初始化validator-rules
					// 初始化validation
					uris[i] = CreateJavascriptUtil.class.getResource(cfgFileNames[i]).toURI().toString();
				}
				resources = new ValidatorResources(uris);
			}
		}
		catch (Exception e)
		{
			log.error("CreateJavascriptUtil.initVR()出错!",e);
			ExceptionMessageParam emp=new ExceptionMessageParam();
			emp.setKeyOrMessageText("CreateJavascriptUtil.initVR()出错!");
			emp.setMessage(true);
			try
			{
				throw new SysException(emp,e);
			}
			catch (SysException e1)
			{
				log.error("CreateJavascriptUtil.initVR()==>throw new MyFrameworkException("+emp+","+e+")出错!",e);
			}
		}
	}
	


	/**
	 * 根据formName取出validation.xml中配置的javascript表单验证代码
	 * @param formName
	 * @return 成功返回map(jsFunctionName,javascript代码)注：javascript代码还不是真正可执行的，需要替换一些标识符后才可，否则返回null
	 */
	private Map<String,String> getJavascriptByForm(String formName)
	{
		Map<String,String> formMapScript=new HashMap<String,String>();
		Form form = resources.getForm(Locale.getDefault(), formName);// 取得配置文件中对应的form表单对象
		Iterator itFields=form.getFields().iterator();
		/**
		 * 找出所有的field
		 */
		while (itFields.hasNext())
		{
			Field field = (Field) itFields.next();
			/**
			 * 找出每个field配置的javascript method
			 */
			Iterator itDependency=field.getDependencyList().iterator();
			while (itDependency.hasNext())
			{
				String dependName = (String) itDependency.next();
				ValidatorAction action = resources.getValidatorAction(dependName);
				formMapScript.put(action.getJsFunctionName(),action.getJavascript());
			}
		}
		return formMapScript.size()==0?null:formMapScript;
	}


	/**
	 * 创建检查fieldName的javascript入口函数
	 * @param mScriptProcessed
	 * @param field
	 * @return 失败返回""否则返回javascript内容
	 */
	@SuppressWarnings("unchecked")
	private String createCallFieldValidatorMethod(String vFormClassName,Field field,Map mScriptProcessed)
	{
		StringBuilder sb=new StringBuilder();
		sb.append("\nthis.call_"
				+ StringUtil.replace(field.getProperty(),".","_")+"=function()\n{");
		sb.append("\nvar field=document.all[\""+field.getProperty()+"\"];\n");
		sb.append("if(field==null){return 0;\n}");
		sb.append("\nvar returnValue=0;\n");//返回值大0说明有错误

		Iterator itDepend=field.getDependencyList().iterator();//每个depend名称对应的script内容
		while (itDepend.hasNext())
		{
			String dependName = (String) itDepend.next();
			ValidatorAction action =null;
			action = resources.getValidatorAction(dependName);
			
			
			int formatsLen=1;
			if(field.getVars()!=null&&field.getVars().size()>0)
			{
				formatsLen=field.getVars().size()+formatsLen;
			}
			String[] formats=new String[formatsLen];//格式化显示信息的参数
			formats[0]=SystemCfgHelper.getValidateFormPropertiesMsg(field.getProperty(),vFormClassName);//StringUtil.getLocalResourceStr(field.getProperty(),"validateFormCfg");
			
			int i=1;//提示信息带有参数的变量都从第二个开始第一个是field名称
			Iterator itKeys=field.getVars().keySet().iterator();
			while (itKeys.hasNext())
			{
				String k=(String)itKeys.next();
				formats[i]=((Var)field.getVars().get(k)).getValue();
				String v="\nfield.setAttribute(\""+k+"\",\""+formats[i]+"\");\n";
				if(sb.indexOf(v)<0)//过滤重复setAttribute()内容
				{
					sb.append(v);//这个脚本只支持IE
				}
				i++;
			}
			
			String msg=SystemUtil.getFrameworkDefaultResourceValue(action.getMsg());
			msg=MessageFormat.format(msg,(Object[])formats);//提示信息与变量次序有关系配置validation.xml需要注意一下


			
			sb.append("\n returnValue+="+action.getJsFunctionName()+"(field,\""+msg+ "\");\n");
		}
		sb.append("\n return returnValue;\n");
		sb.append("\n}\n");
		return sb.toString();
	}
	/**
	 * 生成客户端的javascript检查函数

	 * @param xmlFormName 在validation.xml中的form name
	 * @param formName 在jsp表单中的名称
	 * @return
	 */
	public String createOnSubmitMethod(String xmlFormName,String formName)
	{
		Map mScriptProcessed=null;

		Form form = resources.getForm(Locale.getDefault(), xmlFormName);// 取得配置文件中对应的form表单对象
		Iterator itField=form.getFields().iterator();
		StringBuilder sb=new StringBuilder("<script language=\"javascript\">");
		StringBuilder sbScript=new StringBuilder();
		sb.append("\n function _"+formName+"_check()\n{\n");

		
		mScriptProcessed=getJavascriptByForm(xmlFormName);//this.createValidatorFieldScript(xmlCfgFormName,field.getProperty());
		Iterator itScriptKey=mScriptProcessed.keySet().iterator();
		while (itScriptKey.hasNext())
		{
			String keyName = (String) itScriptKey.next();
			sbScript.append(mScriptProcessed.get(keyName)+"\n");
		}
		
		StringBuilder callAllMehtod=new StringBuilder("function "+formName+"_OnSubmit()\n{");
		callAllMehtod.append("var f=new _"+formName+"_check();\n");
		callAllMehtod.append("var retu=0;\n");
		while (itField.hasNext())
		{
			Field field = (Field) itField.next();
			callAllMehtod.append("retu+=f.call_"+StringUtil.replace(field.getProperty(),".","_")+"();\n");
			sb.append(createCallFieldValidatorMethod(xmlFormName,field,mScriptProcessed));
		}
		
		callAllMehtod.append("if(retu>0)\n{\nreturn false;\n}else{return true;}\n");
		callAllMehtod.append("}\n");
		
		sb.append("\n}\n");
		sb.append(callAllMehtod.toString());
		sb.append(sbScript.toString());
		sb.append("function initOnload(){");
		sb.append("var form1=document.forms[\""+formName+"\"];");
		sb.append("form1.oldSubmit=form1.submit;\n");
		sb.append("form1.oldOnSubmit=form1.onsubmit;\n");
		sb.append("form1.submit=function(){clearAllErrorMsg();if("+formName+"_OnSubmit()){isSubmiting=true;showPaddingDiv();form1.oldSubmit();}}\n");
		sb.append("form1.onsubmit=function(){clearAllErrorMsg();if("+formName+"_OnSubmit()){isSubmiting=true;showPaddingDiv();form1.oldOnSubmit();return true;}return false;}\n");
		sb.append("}");
		sb.append(loadValidateJavascriptUtiles());
		sb.append("window.attachEvent(\"onload\",initOnload);");
		
		sb.append("\n</script>\n");
		return sb.toString();
	}
	/**
	 * 取得本包位置下的javascript uitiles文件
	 * @return
	 */
	private String loadValidateJavascriptUtiles()
	{
		DataInput dis = new DataInputStream(this.getClass().getResourceAsStream("validateJavascriptUtiles.js"));
		try
		{
			String str=null;
			String retu="";
			while ((str=dis.readLine())!=null)
			{
				retu+=str+"\n";
			}
			return retu;
		}
		catch (IOException e)
		{
			log.error("CreateJavascriptUtil.loadValidateJavascriptUtiles()出错\n可能"+this.getClass().getResource("validateJavascriptUtiles.js")+"文件没找到",e);
			return "";
		}
	}
	public static void main(String[] args)
	{
		CreateJavascriptUtil mju=new CreateJavascriptUtil();
		System.out.println(mju.createOnSubmitMethod("com.wonders.scheme.struts.form.SchemeStepForm","SchemeStepForm"));
	}
}
